package ks

import (
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/url"
	"sort"
	"strconv"
	"strings"
	"time"
)

var Acctoken string

// GetRandStr 获取随机字符串
func GetRandStr() string {
	rand.Seed(time.Now().UnixNano())
	charset := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	randomString := make([]byte, 10)
	for i := range randomString {
		randomString[i] = charset[rand.Intn(len(charset))]
	}
	return string(randomString)
}

// GetAccessToken 获取AccessToken
func GetAccessToken(appid, appsecret string) (string, error) {
	// 设置请求参数
	params := url.Values{}
	params.Set("app_id", appid)
	params.Set("app_secret", appsecret)
	params.Set("grant_type", "client_credentials")

	// 发送POST请求
	resp, err := http.PostForm("https://open.kuaishou.com/oauth2/access_token", params)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	// 处理响应结果
	body, err := ioutil.ReadAll(resp.Body)
	var tokenResponse AccessTokenResponse
	err = json.Unmarshal(body, &tokenResponse)
	if err != nil {
		return "", err
	}
	if tokenResponse.Result != 1 {
		return "", err
	}
	return tokenResponse.AccessToken, nil
}

// GetSign 获取签名
func GetSign(params map[string]string, appSecret string) string {
	// 将参数名按字典序升序排序
	keys := make([]string, 0, len(params))
	for k := range params {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	// 拼接参数名和参数值
	var sb strings.Builder
	for i, k := range keys {
		sb.WriteString(k)
		sb.WriteString("=")
		sb.WriteString(params[k])
		if i < len(keys)-1 {
			sb.WriteString("&")
		}
	}
	sb.WriteString(appSecret)
	str := sb.String()
	// 计算MD5值
	h := md5.New()
	h.Write([]byte(str))
	sign := hex.EncodeToString(h.Sum(nil))
	return sign
}

// BindRoom 启动绑定直播间
func BindRoom(appid, appSecret, roomCode, roundId string) BindRoomRes {
	url := "https://open.kuaishou.com/openapi/developer/live/data/task/start" + AddUrl(appid, Acctoken)
	timestamp := time.Now().UnixNano()
	Sign := GetSign(map[string]string{
		"app_id":    appid,
		"roomCode":  roomCode,
		"roundId":   roundId,
		"timestamp": strconv.FormatInt(timestamp/1e6, 10),
	}, appSecret)

	data := BindRoomReq{
		RoomCode:  roomCode,
		Timestamp: timestamp,
		Sign:      Sign,
		RoundId:   roundId,
	}
	marshal, _ := json.Marshal(data)

	payload := strings.NewReader(string(marshal))

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Content-Type", "application/json;charset=UTF-8")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)

	var resp BindRoomRes
	json.Unmarshal(body, &resp)
	return resp
}

// UnBindRoom 解绑直播间
func UnBindRoom(appid, appSecret, roomCode, roundId string) UnBindRoomRes {
	url := "https://open.kuaishou.com/openapi/developer/live/data/task/stop" + AddUrl(appid, Acctoken)
	timestamp := time.Now().UnixNano()
	Sign := GetSign(map[string]string{
		"app_id":    appid,
		"roomCode":  roomCode,
		"roundId":   roundId,
		"timestamp": strconv.FormatInt(timestamp/1e6, 10),
	}, appSecret)

	data := BindRoomReq{
		RoomCode:  roomCode,
		Timestamp: timestamp,
		Sign:      Sign,
		RoundId:   roundId,
	}
	marshal, _ := json.Marshal(data)

	payload := strings.NewReader(string(marshal))

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Content-Type", "application/json;charset=UTF-8")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)

	var resp UnBindRoomRes
	json.Unmarshal(body, &resp)
	return resp
}

// QueryLiveStatus 查询绑定直播间任务状态
func QueryLiveStatus(appid, appSecret, roomCode string) QueryStatusRes {
	url := "https://open.kuaishou.com/openapi/developer/live/data/task/status" + AddUrl(appid, Acctoken)
	timestamp := time.Now().UnixNano()
	Sign := GetSign(map[string]string{
		"app_id":    appid,
		"roomCode":  roomCode,
		"timestamp": strconv.FormatInt(timestamp/1e6, 10),
	}, appSecret)

	data := QueryStatusReq{
		RoomCode:  roomCode,
		Timestamp: timestamp,
		Sign:      Sign,
	}
	marshal, _ := json.Marshal(data)

	payload := strings.NewReader(string(marshal))

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Content-Type", "application/json;charset=UTF-8")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)

	var resp QueryStatusRes
	json.Unmarshal(body, &resp)
	return resp
}

// GiftTop 礼物置顶
func GiftTop(appid, appSecret, roomCode, giftList string, giftExtendInfo []GiftExtendInfo) GiftTopRes {
	url := "https://open.kuaishou.com/openapi/developer/live/interactive/gift/top" + AddUrl(appid, Acctoken)
	timestamp := time.Now().UnixNano()
	bytes, _ := json.Marshal(giftExtendInfo)

	Sign := GetSign(map[string]string{
		"app_id":         appid,
		"roomCode":       roomCode,
		"giftList":       giftList,
		"giftExtendInfo": string(bytes),
		"timestamp":      strconv.FormatInt(timestamp/1e6, 10),
	}, appSecret)

	data := GiftTopReq{
		RoomCode:       roomCode,
		Timestamp:      timestamp,
		GiftList:       giftList,
		Sign:           Sign,
		GiftExtendInfo: giftExtendInfo,
	}
	marshal, _ := json.Marshal(data)

	payload := strings.NewReader(string(marshal))

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Content-Type", "application/json;charset=UTF-8")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)

	var resp GiftTopRes
	json.Unmarshal(body, &resp)
	return resp
}

// CommentTop 评论置顶
func CommentTop(appid, appSecret, roomCode, roundId string, commentTopReqData CommentTopReqData) CommentTopRes {
	url := "https://open.kuaishou.com/openapi/developer/live/interactive/gift/top" + AddUrl(appid, Acctoken)
	timestamp := time.Now().UnixNano()
	bytes, _ := json.Marshal(commentTopReqData)
	Sign := GetSign(map[string]string{
		"app_id":    appid,
		"roomCode":  roomCode,
		"roundId":   roundId,
		"type":      "1",
		"data":      string(bytes),
		"timestamp": strconv.FormatInt(timestamp/1e6, 10),
	}, appSecret)

	data := CommentTopReq{
		RoomCode:  roomCode,
		Timestamp: timestamp,
		Sign:      Sign,
		RoundId:   roundId,
		Type:      "1",
		Data:      commentTopReqData,
	}

	marshal, _ := json.Marshal(data)
	payload := strings.NewReader(string(marshal))
	req, _ := http.NewRequest("POST", url, payload)
	req.Header.Add("Content-Type", "application/json;charset=UTF-8")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)

	var resp CommentTopRes
	json.Unmarshal(body, &resp)
	return resp
}

func AddUrl(appid string, acctoken string) string {
	return "?app_id=" + appid + "&access_token=" + acctoken
}
